import { BaseMode } from "./interface";
import { Utils } from "./util";

let util = new Utils();
let passcode = "secret passcode";

class MyClass {}
export class ClassTest implements BaseMode{
    run (){       
        const instance = new MyClass();
        util.log(instance.constructor.name,"show class name with instance"); // MyClass
        util.log(MyClass.name,"show class name with Class"); 

        let greeter = new Greeter("world");
        util.log(greeter.greet(),"Class Greeter");

        let sam = new Snake("Sammy the Python");
        let tom: Animal = new Horse("Tommy the Palomino");
        sam.move();
        tom.move(34);
        let animal = new Animal("base");
        animal = sam;
        util.log(animal.name,"show Animal=Snake");

        //getters&setters
        passcode = "secret passcode error";
        let employee = new Employee();
        employee.fullName = "Bob Smith";
        if (employee.fullName) {
            util.log(employee.fullName,"class getter");
        }

        //static
        let grid1 = new Grid(1.0);  // 1x scale
        let grid2 = new Grid(5.0);  // 5x scale

        util.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10}),"scale 1.0");
        util.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}),"scale 5.0");

        //nothing different
        let grideMaker:typeof Grid = Grid;
        let clsGride = Grid;

        util.log(grideMaker,"grideMaker");
        // util.log(clsGride === grideMaker ,"typeof Grid =?= Grid");
        util.log(clsGride,"class Grid");
        // util.log(typeof iGrid,"typeof iGrid");
        grideMaker.origin = {x:5,y:5};

        let grideInstace = new grideMaker(0.5);
        util.log(grideInstace.calculateDistanceFromOrigin({x: 10, y: 10}),"grideMaker scale 0.5");
    }
}

//base
class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}

//继承
//参数属性
class Animal {
    // name:string;
    //参数属性
    constructor(public name: string) { 
        // this.name = theName; 
    }
    move(distanceInMeters: number = 0) {
        util.log(`${this.name} moved ${distanceInMeters}m.`,this.constructor.name+" move");
    }
}

class Snake extends Animal {
    constructor(name: string) { super(name); }
    move(distanceInMeters = 5) {
        util.log("Slithering...",this.constructor.name);
        super.move(distanceInMeters);
    }
}

class Horse extends Animal {
    constructor(name: string) { super(name); }
    move(distanceInMeters = 45) {
        util.log("Galloping...",this.constructor.name);
        super.move(distanceInMeters);
    }
}

// readonly for class property
class Octopus {
    readonly name: string;
    readonly numberOfLegs: number = 8;
    constructor (theName: string) {
        this.name = theName;
    }
}

//getters & setters
class Employee {
    private _fullName: string;

    get fullName(): string {
        return this._fullName;
    }

    set fullName(newName: string) {
        if (passcode && passcode == "secret passcode") {
            this._fullName = newName;
        }
        else {
            util.log("Error: Unauthorized update of employee!","setter");
        }
    }
}

//static 
class Grid {
    static origin = {x: 0, y: 0};
    calculateDistanceFromOrigin(point: {x: number; y: number;}) {
        let xDist = (point.x - Grid.origin.x);
        let yDist = (point.y - Grid.origin.y);
        return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
    }
    constructor (public scale: number) { }
}

interface iGrid extends Grid{
    iExt:string;
}